﻿using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using BitsOfStuff.Support;

namespace BitsOfStuff
{
    internal class MyShape
    {
        private List<MyLine> _myLines;
        private readonly List<MySelectedPoint> _selectedPoints;
        private readonly List<int> _segmentSequence;
        private int _userDiverse;
        private int[] _curentAxes;
        private readonly bool _shortShape;

        public List<int> getSequence()
        {
            if (!_shortShape)
                return _segmentSequence;
            return new List<int> { ShortShapeRecognition.getShortSequence() };
        }

        public MyShape(List<MySelectedPoint> mySelectedPoints)
        {
            _selectedPoints = new List<MySelectedPoint>(mySelectedPoints);
            if (mySelectedPoints.Count < 3) // posible short object
            {
                _shortShape = true;
                foreach (MySelectedPoint item in mySelectedPoints)
                {
                    if (!(item is ShortPoint))
                    {
                        _shortShape = false;
                        break;
                    }
                }
            }

            _myLines = new List<MyLine>();
            for (int i = 0; i < mySelectedPoints.Count - 1; i++)
            {
                _myLines.Add(MyLine.createLine(mySelectedPoints[i], mySelectedPoints[i + 1]));
            }
            _segmentSequence = new List<int>();
            _userDiverse = new int();
            _curentAxes = createAxisBorders(_userDiverse, MyParameters.shapeCountOfsectors, MyParameters.shapeStartAngle);
        }

        public void setUserDiverse(int diverse)
        {
            _userDiverse = diverse + MyParameters.shapeAxesDiversion;
            _curentAxes = createAxisBorders(_userDiverse, MyParameters.shapeCountOfsectors, MyParameters.shapeStartAngle);
        }

        public void assignSegments()
        {
            _myLines.RemoveAll(lines => lines.Vector.getVectorLength() < 20);

            if (!_shortShape)
                foreach (MyLine myLine in _myLines)
                {
                    myLine.getFreemanCode(_userDiverse, _curentAxes);
                }
        }

        public void mergeSameSegmentsLine()
        {
            if (_shortShape)
                return;
            var result = new List<MyLine>();
            int startIndex = 0;
            int endIndex = 0;
            if (_myLines.Count == 0)
            {
                return;
            }
            int curentSector = _myLines[0].getFreemanCode(_userDiverse, _curentAxes);
            for (int i = 0; i < _myLines.Count; i++)
            {
                if (curentSector != _myLines[i].getFreemanCode(_userDiverse, _curentAxes))
                {
                    _segmentSequence.Add(curentSector);
                    result.Add(MyLine.createLine(
                        _myLines[startIndex].Vector.getStartPoint(),
                        _myLines[i - 1].Vector.getEndPoint()));
                    curentSector = _myLines[i].getFreemanCode(_userDiverse, _curentAxes);

                    startIndex = i;
                }
            }
            _segmentSequence.Add(curentSector);
            var lastOrDefault = _myLines.LastOrDefault();
            if (lastOrDefault != null)
                result.Add(MyLine.createLine(
                    _myLines[startIndex].Vector.getStartPoint(),
                    lastOrDefault.Vector.getEndPoint()));
            //Remove pipes

            _myLines = SupportFunctions.pipeCompensation(result);
        }

        public void drawn(InkCanvas inkCanvas)
        {
            foreach (MyLine myLine in _myLines)
            {
                myLine.drawn(inkCanvas);
            }
        }

        private int[] createAxisBorders(int diversion, int sectorCount, int startAngle)
        {
            var result = new int[sectorCount];

            int angleStep = 360 / sectorCount;

            for (int i = 0; i < sectorCount; i++)
            {
                result[i] = startAngle + angleStep * i + diversion;
            }

            return result;
        }

        public void clearSequence()
        {
            _segmentSequence.Clear();
        }

        public List<MySelectedPoint> getSelectedPoint()
        {
            return _selectedPoints;
        }

        public MyPoint getShapeStartPoint()
        {
            var mySelectedPoint = _selectedPoints.FirstOrDefault();
            if (mySelectedPoint != null) return mySelectedPoint.getPoint();
            return new MyPoint();
        }

        public double getShapeWeigth()
        {
            return _selectedPoints.Max(point => point.getPoint().getY()) - _selectedPoints.Min(point => point.getPoint().getY());
        }

        public double getShapeHeigth()
        {
            return _selectedPoints.Max(point => point.getPoint().getX()) - _selectedPoints.Min(point => point.getPoint().getX());
        }

        public double getShapeSize()
        {
            if (getShapeHeigth() > getShapeWeigth())
                return getShapeHeigth();
            return getShapeWeigth();
        }
    }
}